package cn.xiaolang.thread.async;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

import org.springframework.util.StopWatch;

public class SyncVsAsyncSample {

    private static final ExecutorService threadPool = Executors.newFixedThreadPool(10);
    private static List<Future<String>> futures = new ArrayList<>();
    private static List<Callable<String>> callables = new ArrayList<>();

    public static void main(String[] args) throws InterruptedException {

        syncHandler();
        asyncHandler();
        asyncHandlerByInvokeAll();
        threadPool.shutdown();

    }

    private static void asyncHandlerByInvokeAll() throws InterruptedException {
        StopWatch sw = new StopWatch("async-invoke-all");
        sw.start();
        callables.add(getCallable(1));
        callables.add(getCallable(2));
        callables.add(getCallable(3));
        callables.add(getCallable(4));
        List<Future<String>> result = threadPool.invokeAll(callables);
        result.stream().forEach(a -> {
            try {
                System.out.println(a.get());
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        });
        sw.stop();
        System.err.println(sw.prettyPrint());
    }

    private static Callable<String> getCallable(int step) {
        return () -> {
            try {
                Thread.sleep(1000 * step);
                return "exec: step " + step;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "nothing";
        };
    }


    private static void asyncHandler() {
        StopWatch sw = new StopWatch("async");
        sw.start();
        futures.add(submitTask(1));
        futures.add(submitTask(2));
        futures.add(submitTask(3));
        futures.add(submitTask(4));
        futures.stream().forEach(a -> {
            try {
                System.out.println(a.get());
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        });
        sw.stop();
        System.err.println(sw.prettyPrint());
        futures.clear();
    }

    private static Future<String> submitTask(int step) {
        return threadPool.submit(() -> {
            try {
                Thread.sleep(1000 * step);
                return "exec: step " + step;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "nothing";
        });
    }

    public static void syncHandler() throws InterruptedException {
        StopWatch sw = new StopWatch("sync");
        sw.start();

        System.out.println("exec: step 1");
        Thread.sleep(1000);

        System.out.println("exec: step 2");
        Thread.sleep(2000);

        System.out.println("exec: step 3");
        Thread.sleep(3000);

        System.out.println("exec: step 4");
        Thread.sleep(4000);

        sw.stop();
        System.err.println(sw.prettyPrint());
    }
}
